home *** CD-ROM | disk | FTP | other *** search
/ FM Towns: Free Software Collection 11 / FM Towns Free Software Collection 11.iso / t_os / tool / artemis1 / src / pattern.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-14  |  38.9 KB  |  1,716 lines

  1. /*
  2.     pattern.c
  3.  
  4.     グラフィックのパターン化
  5. */
  6.  
  7. #include <stdio.h>
  8. #include <malloc.h>
  9. #include <string.h>
  10. #include <memory.h>
  11. #include <stdlib.h>
  12.  
  13. #include "ge.h"
  14. #include "dispman.h"
  15. #include "imageman.h"
  16. #include "mask.h"
  17.  
  18. typedef struct _pat
  19. {
  20.     struct _pat    *next;            // リスト化のためのポインタ
  21.     char        name[41];        // パターン名(漢字で20文字まで)
  22.     char        subname[15];    // パターンの略称(漢字で 7 文字まで)
  23.     int            xlen, ylen;        // パターンの大きさ
  24.     int            bufx, bufy;        // パターンバッファ内での位置
  25.     int            patbufsize;        // パターンデータのバイト数
  26.     char        *patbuf;        // パターンデータへのポインタ
  27.     bool        selected;        // 選択されているなら YES
  28.     bool        nodisp;            // パターンバッファ表示時に表示しないなら YES
  29.     int            zoomx,zoomy;    // パターンの1ドットの縦横比率
  30.     bool        nowdisp;        // 画面に表示されているなら YES
  31.     char        dmy[33];        // 埋め草
  32. } PAT;   // size = 128 bytes
  33.  
  34. #define    PATZOOM    2
  35.  
  36. #define    constPAT(p)        ((p) = calloc(sizeof(PAT),1))
  37. #define    destroyPAT(p)    {if((p)->patbuf!=NULL) free((p)->patbuf); free((p));}
  38.  
  39. // #define    SELNUM    1000            /* パターンを幾つまで選択できるか */
  40. // static    PAT        *selpat[SELNUM];
  41. // static    int        selnum = -1;
  42.  
  43. // static    char    *scrbuf = NULL;        // パターン編集に入る前の画面を保存するバッファ
  44. static    PAT        *patlist = NULL;
  45. static    PAT        *curpat = NULL;        // 右クリックされたパターンを指すポインタ
  46.  
  47.  
  48. /*--------------------------------------------------------*/
  49. /*                     メニューの定義                     */
  50. /*--------------------------------------------------------*/
  51.  
  52.  
  53. #define    itemExit            1
  54. #define    itemPatBuf            2
  55.  
  56.  
  57. static void disp_patterns_all_new();
  58. static void disp_patmenu(),erase_patmenu();
  59.  
  60.     void    dsppatname(),dsppatsubname();
  61.     #define    IP(n)    menu_button(&patsubmenu,n)
  62.     static void disp_patsubmenu(), erase_patsubmenu();
  63.  
  64. #include "pattern.md"
  65.  
  66. static void disp_patmenu()
  67. {
  68. }
  69.  
  70. static void erase_patmenu()
  71. {
  72. }
  73.  
  74.  
  75. /*--------------------------------------------------------*/
  76. /*                   サブメニューの定義                   */
  77. /*--------------------------------------------------------*/
  78.  
  79.  
  80. int    cntcolor();
  81.  
  82.  
  83. static    void    dsppatname()
  84. {
  85.     int ixlen;
  86.     menu_getbuttonxy(&patsubmenu, SitemPatName, NULL,NULL,&ixlen,NULL);
  87.     char strbuf[40];
  88.     int i;
  89.     for (i=0; i<ixlen/8; i++)
  90.         strbuf[i] = curpat->name[i];
  91.     strbuf[i] = '\0';
  92.    menu_buttonputstr(menu_button(&patsubmenu,SitemPatName),1,1,strbuf,typeSTR);
  93. }
  94.  
  95.  
  96. static    void    dsppatsubname()
  97. {
  98.     menu_buttonputstr(IP(SitemPatSubName),1,1, curpat->subname, typeSTR);
  99. }
  100.  
  101.  
  102. static void disp_patsubmenu()
  103. {
  104.     char strbuf[100];
  105.     sprintf(strbuf, "%d", curpat->xlen);
  106.     menu_buttonputstr(IP(SitemPatXLen), 16,0, strbuf,typeSTR);
  107.     sprintf(strbuf, "%d", curpat->ylen);
  108.     menu_buttonputstr(IP(SitemPatYLen), 16,0, strbuf,typeSTR);
  109.     sprintf(strbuf, "%d", cntcolor(curpat));
  110.     menu_buttonputstr(IP(SitemColNum), 72,0, strbuf,typeSTR);
  111.     // sprintf(strbuf, "(%2d,%2d)", curpat->zoomx, curpat->zoomy);
  112.     // menu_buttonputstr(IP(SitemDotZoom), 88,0, strbuf,typeSTR);
  113. }
  114.  
  115.  
  116. static void erase_patsubmenu()
  117. {
  118. }
  119.  
  120.  
  121. /*--------------------------------------------------------*/
  122. /*                        補助処理                        */
  123. /*--------------------------------------------------------*/
  124.  
  125.  
  126. // ● ページ1の拡大率・表示位置を設定する
  127.  
  128.  
  129. static int pre_zoom,pre_zoomY;
  130. static int pre_dispX, pre_dispY;
  131. static bool pre_lat1disp,pre_lat2disp;
  132.  
  133.  
  134. static void resetPage1()
  135. {
  136.     DMimage_setzoomrate(pre_zoom);
  137.     DMimage_setdispxy(pre_dispX,pre_dispY);
  138.     DMimage_setlatticeswitch(pre_lat1disp,pre_lat2disp);
  139.     DMimage_refresh();
  140. }
  141.  
  142.  
  143. static void setPage1()
  144. {
  145.     pre_zoom = DMimage_getzoomrate();
  146.     DMimage_getdispxy(&pre_dispX, &pre_dispY);
  147.     DMimage_getlatticeswitch(&pre_lat1disp,&pre_lat2disp);
  148.     DMimage_setlatticeswitch(NO,NO);
  149.     DMimage_setzoomrate(2);
  150.     DMimage_setdispxy(0,0);
  151. }
  152.  
  153.  
  154. // ● 現在編集している画面をメモリに保存/復帰する
  155.  
  156.  
  157.  
  158. // ● ページ0の座標をページ1の座標に変換する
  159.  
  160.  
  161. // ●パターンの特定のドットの色コードを調べる
  162.  
  163.  
  164. static int get_pat_pixel(PAT *pp, int x, int y)
  165. // (x,y) : パターン内でのオフセット
  166. {
  167.     if (mode == MODE32K)
  168.         return *(short int *)(pp->patbuf + (pp->xlen*2) * y + x * 2);
  169.     else
  170.     {
  171.         int c;
  172.         c = *(pp->patbuf + ((pp->xlen+7)/8)*4 * y + x/2);
  173.         if ((x&1) == 0)
  174.             return c&15;
  175.         else
  176.             return (c>>4)&15;
  177.     }
  178. }
  179.  
  180.  
  181. // ●パターンリストにいくつのパターンが登録されているか調べる
  182.  
  183.  
  184. static int get_patallnum()
  185. {
  186.     PAT *pp;  int n;
  187.     for (pp=patlist, n=0;  pp != NULL;  pp = pp->next, n++)
  188.         ;
  189.     return n;
  190. }
  191.  
  192.  
  193. // ●パターンがリスト内で何番目かをしらべる
  194.  
  195.  
  196. static int get_patnum(PAT *patp)
  197. {
  198.     PAT *pp;
  199.     int n;
  200.     for (pp=patlist, n=0;  pp != NULL;  pp = pp->next, n++) {
  201.         if (pp == patp)
  202.             return n;
  203.     }
  204.     return -1;
  205. }
  206.  
  207.  
  208. // ●パターンリストを、パターン名をキーにしてソートする
  209.  
  210.  
  211.     static int cmp_patname(PAT **p1, PAT **p2)
  212.     {
  213.         return strcmp((*p1)->name, (*p2)->name);
  214.     }
  215.  
  216.  
  217. static void sort_patlist()
  218. {
  219.     int patallnum,i;   PAT **plist,*pp;
  220.     if ((patallnum = get_patallnum()) == 0)
  221.         return;
  222.     if ((plist = (PAT**)malloc(sizeof(PAT *) * patallnum)) == NULL)
  223.         return;
  224.     for (i=0,pp=patlist; i<patallnum; i++,pp=pp->next)
  225.         *(plist + i) = pp;
  226.  
  227.     qsort(plist, patallnum, sizeof(PAT*), cmp_patname);
  228.  
  229.     patlist = *(plist+0);
  230.     for (i=0; i<patallnum-1; i++)
  231.         (*(plist+i))->next = *(plist+i+1);
  232.     (*(plist+patallnum-1))->next = NULL;
  233.     free(plist);
  234. }
  235.  
  236.  
  237. // ● パターンバッファ内での座標を 640*480座標に変換する
  238.  
  239.  
  240. static void bufp_to_page0p( int x,int y,int xlen,int ylen,
  241.                             int *dx,int *dy,int *dxlen,int *dylen )
  242. {
  243.     BUTTON *ip;  int zr=DMimage_getzoomrate();
  244.     int ix,iy,ixlen,iylen;
  245.     menu_getbuttonxy(&patternmenu,itemPatBuf,&ix,&iy,&ixlen,&iylen);
  246.     if (dx!=NULL)
  247.         *dx = ix  + x * zr;
  248.     if (dy!=NULL)
  249.         *dy = iy  + y * zr;
  250.     if (dxlen != NULL)
  251.         *dxlen = xlen * zr;
  252.     if (dylen != NULL)
  253.         *dylen = ylen * zr;
  254. }
  255.  
  256.  
  257. /*--------------------------------------------------------*/
  258. /*               パターンの表示・消去の処理               */
  259. /*--------------------------------------------------------*/
  260.  
  261.  
  262. static char *get_pat_disp_name(PAT *pp)
  263. /*
  264.     パターン pp の画面上での名前を得る(最大30文字ぐらい)
  265.     これは、関数内文字列バッファへのポインタを返す。
  266. */
  267. {
  268.     char name[15];
  269.     static char buf[30];
  270.     if (pp->subname[0] != '\0')
  271.         strncpy(name,pp->subname,14);
  272.     else
  273.         strncpy(name,pp->name,14);
  274.     sprintf(buf, "%d:%s", get_patnum(pp), name);
  275.     return buf;
  276. }
  277.  
  278.  
  279. static void get_pat_name_area(PAT *pp, int *x, int *y, int *xlen, int *ylen)
  280. /*
  281.     パターン pp の名前表示のための領域(640*480座標内)を得る
  282. */
  283. {
  284.     int namex,namey; BUTTON *ip;  int zr=DMimage_getzoomrate();
  285.     ip = menu_button(&patternmenu,itemPatBuf);
  286.     int ix,iy;
  287.     menu_getbuttonxy(&patternmenu,itemPatBuf,&ix,&iy,NULL,NULL);
  288.     namex = ix + (pp->bufx + pp->xlen/2) * zr
  289.             - (8 * strlen(get_pat_disp_name(pp))) / 2;
  290.     namey = iy + (pp->bufy + pp->ylen) * zr + 2;
  291.     if (x != NULL)
  292.         *x = namex;
  293.     if (y != NULL)
  294.         *y = namey;
  295.     if (xlen != NULL)
  296.         *xlen = 8 * strlen(get_pat_disp_name(pp));
  297.     if (ylen != NULL)
  298.         *ylen = 16;
  299. }
  300.  
  301.  
  302. // ●パターンひとつを表示する
  303.  
  304.  
  305. static void dispOnePattern(PAT *pp, bool frame, bool center)
  306. // frame : 枠とパターン名を表示するかどうか
  307. {
  308.     BUTTON *ip;  int bx0,by0, px,py;  int menux,menuy;
  309.     menu_getmenuxy(NULL,&menux,&menuy,NULL,NULL);
  310.     int zr=DMimage_getzoomrate();
  311.     ip = menu_button(&patternmenu,itemPatBuf);
  312.     int ix,iy,ixlen,iylen;
  313.     menu_getbuttonxy(&patternmenu,itemPatBuf,&ix,&iy,&ixlen,&iylen);
  314.     bx0 = sx2bx(ix);
  315.     by0 = sy2by(iy);
  316.     if (center) {
  317.         px = (ixlen/zr - pp->xlen*pp->zoomx)/2;
  318.         py = (iylen/zr - pp->ylen*pp->zoomy)/2;
  319.     } else {
  320.         px = pp->bufx;
  321.         py = pp->bufy;
  322.     }
  323.  
  324.     int patxlen,patylen;
  325.     patxlen = pp->xlen * pp->zoomx;
  326.     patylen = pp->ylen * pp->zoomy;
  327.  
  328.     if (pp->nodisp)
  329.         return;
  330.     pp->nowdisp = YES;
  331.     page_edit();
  332.     if (pp->zoomx == 1 && pp->zoomy == 1)
  333.         grp_putblk(bx0+px, by0+py, pp->xlen, pp->ylen, pp->patbuf, DrawNORMAL);
  334.     else if (pp->zoomx == 1) { 
  335.         int y,iy;
  336.         for (y=0;  y < pp->ylen;  y++) {
  337.             char *p;
  338.             if (mode == MODE32K)
  339.                 p = pp->patbuf + pp->xlen*2 * y;
  340.             else
  341.                 p = pp->patbuf + ((pp->xlen+7)/8)*4 * y;
  342.             for (iy=0; iy<pp->zoomy; iy++)
  343.                 grp_putblk(bx0+px,by0+py+y*pp->zoomy+iy,pp->xlen,1,
  344.                            p, DrawNORMAL);
  345.         }
  346.     } else {
  347.         int x,y;
  348.         for (y=0;  y < pp->ylen;  y++) {
  349.             for (x=0;  x < pp->xlen;  x++) {
  350.                 int c;
  351.                 if (mode == MODE32K)
  352.                     c = *(short int *)(pp->patbuf + pp->xlen*2 * y + x*2);
  353.                 else {
  354.                     c = *(pp->patbuf + ((pp->xlen+7)/8)*4 * y + x/2);
  355.                     if ((x&1) == 0)
  356.                         c = c & 0xf;
  357.                     else
  358.                         c = (c >> 4);
  359.                 }
  360.                 grboxfill(bx0+px+x*pp->zoomx, by0+py+y*pp->zoomy,
  361.                           pp->zoomx,pp->zoomy,c,DrawNORMAL);
  362.             }
  363.         }
  364.     }
  365.     if (pp->selected)
  366.         grboxfill(bx0+px,by0+py,patxlen,patylen,white,DrawXOR);
  367.     page_menu();
  368.  
  369.     if (frame) {
  370.         int namex,namey;
  371.         get_pat_name_area(pp,&namex,&namey,NULL,NULL);
  372.         ART_putstr(namex,namey,get_pat_disp_name(pp),COL_menuString);
  373.         {
  374.             int patx,paty,patxl,patyl;
  375.             bufp_to_page0p(px,py,pp->xlen*pp->zoomx,pp->ylen*pp->zoomy,&patx,&paty,&patxl,&patyl);
  376.             grboxline(patx-1,paty-1, patxl+2,patyl+2, White,DrawNORMAL);
  377.             grboxfill(patx,  paty,   patxl,  patyl,   Black0,DrawNORMAL);
  378.         }
  379.     }
  380. }
  381.  
  382.  
  383. // ● 画面上のパターンを1つ(と、それに重なるパターンを全て)消去する
  384.  
  385. /*
  386.  
  387. static void erase_pattern_one(PAT *pp)
  388. {
  389.     typedef struct {int x,y,xlen,ylen;} area_t;
  390.     bool area_crash(int x1,int y1,int xlen1,int ylen1,int x2,int y2,int xlen2,int ylen2)
  391.     {
  392.         if (((a1.x<=a2.x && a2.x<a1.x+a1.xlen) || (a2.x<=a1.x && a1.x<a2.x+a2.xlen)) &&
  393.             ((a1.y<=a2.y && a2.y<a1.y+a1.ylen) || (a2.y<=a1.y && a1.y<a2.y+a2.ylen)))
  394.             return NO;
  395.     }
  396.     area_t p0,p1,p2,p3;
  397.     bufp_to_page0p( pp->bufx,pp->bufy,pp->xlen*pp->zoomx,pp->ylen*pp->zoomy,
  398.                     &p0.x,&p0.y,&p0.xlen,&p0.ylen );
  399.     get_pat_name_area(pp,&p1.x,&p1.y,&p1.xlen,&p1.ylen);
  400.     PAT *tpp;
  401.     for (tpp=patlist; tpp!=NULL; tpp=tpp->next)
  402.     {
  403.         bufp_to_page0p( tpp->bufx,tpp->bufy,tpp->xlen*tpp->zoomx,tpp->ylen*tpp->zoomy,
  404.                         &p2.x,&p2.y,&p2.xlen,&p2.ylen );
  405.         get_pat_name_area(tpp,&p3.x,&p3.y,&p3.xlen,&p3.ylen);
  406.     }
  407. }
  408. */
  409.  
  410.  
  411. // ● 画面上のパターンを全部消去する
  412.  
  413.  
  414. static void erase_patterns_all()
  415. {
  416.     BUTTON *ip;  int bx0,by0;
  417.     PAT *pp; int menux,menuy;  menu_getmenuxy(NULL,&menux,&menuy,NULL,NULL);
  418.     for (pp=patlist;  pp!=NULL; pp=pp->next)
  419.         pp->nowdisp = NO;
  420.     int ix,iy,ixlen,iylen;
  421.     menu_getbuttonxy(&patternmenu,itemPatBuf,&ix,&iy,&ixlen,&iylen);
  422.     bx0 = sx2bx(ix);
  423.     by0 = sy2by(iy);
  424.     int zr=DMimage_getzoomrate();
  425.     page_edit();
  426.     grboxfill(bx0,by0,ixlen/zr,iylen/zr,Black0,DrawNORMAL);
  427.     page_menu();
  428.     grboxfill(ix,iy,ixlen,iylen,Black0,DrawNORMAL);
  429. }
  430.  
  431.  
  432. // ● パターンリストのパターンの表示を更新する
  433.  
  434.  
  435. static void disp_patterns_makeup()
  436. {
  437.     PAT *pp;
  438.     for (pp = patlist;  pp != NULL;  pp = pp->next)
  439.         dispOnePattern(pp, YES, NO);
  440. }
  441.  
  442.  
  443. // ● パターンリストのパターンを全部表示しなおす
  444.  
  445.  
  446. static void disp_patterns_all_new()
  447. {
  448.     erase_patterns_all();
  449.     disp_patterns_makeup();
  450. }
  451.  
  452.  
  453. // ● 画面上の座標が どのパターンに対応するかを調べる
  454.  
  455.  
  456. static PAT *jdgPattern(int msx, int msy)
  457. {
  458.     BUTTON *ip; int menux,menuy;  menu_getmenuxy(NULL,&menux,&menuy,NULL,NULL);
  459.     int ix,iy;
  460.     menu_getbuttonxy(&patternmenu,itemPatBuf,&ix,&iy,NULL,NULL);
  461.     PAT *pp,*rp;  int zr=DMimage_getzoomrate();
  462.     rp = NULL;
  463.     for (pp=patlist; pp!=NULL; pp=pp->next) {
  464.         int x1,y1,x2,y2;
  465.         x1 = ix+pp->bufx*zr;
  466.         y1 = iy+pp->bufy*zr;
  467.         x2 = x1 + pp->xlen * pp->zoomx * zr - 1;
  468.         y2 = y1 + pp->ylen * pp->zoomy * zr - 1;
  469.         if (x1<=msx && msx<=x2 && y1<=msy && msy<=y2)
  470.             rp = pp;
  471.     }
  472.     return rp;
  473. }
  474.  
  475.  
  476. // ● 特定のパターンに、何色の色が使われているか調べる
  477.  
  478.  
  479. static int cntcolor(PAT *pp)
  480. {
  481.     int i,j,cnt;
  482.     cnt = 0;
  483.     if (mode == MODE32K) {
  484.         short int *p;
  485.         p = (short int *)pp->patbuf;
  486.         bool flgs[32768];
  487.         memset(flgs, NO, 32768);    // 全ての「色使用フラグ」をクリアする
  488.         for (i=0; i < pp->ylen; i++) {
  489.             for (j=0; j < pp->xlen; j++) {
  490.                 if (!flgs[*p]) {
  491.                     cnt++;
  492.                     flgs[*p] = YES;
  493.                 }
  494.                 p++;
  495.             }
  496.         }
  497.     } else {
  498.         char *p;
  499.         p = pp->patbuf;
  500.         int ystep;  bool flgs[16];
  501.         ystep = ((pp->xlen + 7)/8)*4;
  502.         memset(flgs,NO,16);
  503.         for (i=0; i < pp->ylen; i++,p+=ystep) {
  504.             for (j=0; j < pp->xlen; j++) {
  505.                 int c = *(p+j/2);
  506.                 if ((j&1)==0)    c &= 15;
  507.                 else            c >>= 4;
  508.                 if (!flgs[c]) {
  509.                     cnt++;
  510.                     flgs[c] = YES;
  511.                 }
  512.             }
  513.         }
  514.     }
  515.     return cnt;
  516. }
  517.  
  518. // ● ページ0 の座標と パターンバッファの座標を変換する
  519.  
  520. static int sx2bx(int x)
  521. {
  522.     return /* dispX + */ x/DMimage_getzoomrate();
  523. }
  524.  
  525. static int sy2by(int y)
  526. {
  527.     return /* dispY + */ y/DMimage_getzoomrate();
  528. }
  529.  
  530. static int sx2bufx(int x)
  531. {
  532.     int ix;
  533.     menu_getbuttonxy(&patternmenu, itemPatBuf, &ix,NULL,NULL,NULL);
  534.     int zr = DMimage_getzoomrate();
  535.     return (x - ix) / zr;
  536. }
  537.  
  538. static int sy2bufy(int y)
  539. {
  540.     int iy;
  541.     menu_getbuttonxy(&patternmenu, itemPatBuf, NULL,&iy,NULL,NULL);
  542.     int zr = DMimage_getzoomrate();
  543.     return (y - iy) / zr;
  544. }
  545.  
  546. static int bufx2sx(int x)
  547. {
  548.     int ix;
  549.     menu_getbuttonxy(&patternmenu, itemPatBuf, &ix,NULL,NULL,NULL);
  550.     int zr = DMimage_getzoomrate();
  551.     return ix+x*zr;
  552. }
  553.  
  554. static int bufy2sy(int y)
  555. {
  556.     int iy;
  557.     menu_getbuttonxy(&patternmenu, itemPatBuf, NULL,&iy,NULL,NULL);
  558.     int zr = DMimage_getzoomrate();
  559.     return iy+y*zr;
  560. }
  561.  
  562. // ● パターンデータの複製を作る
  563.  
  564. static PAT *dupPAT(PAT *pat)
  565. {
  566.     PAT *newpat;
  567.     if (constPAT(newpat) == NULL)
  568.         return NULL;
  569.     *newpat = *pat;
  570.     if ((newpat->patbuf = malloc(pat->patbufsize)) == NULL) {
  571.         destroyPAT(newpat);
  572.         return NULL;
  573.     }
  574.     memcpy(newpat->patbuf, pat->patbuf, pat->patbufsize);
  575.     return newpat;
  576. }
  577.  
  578. // ● パターンデータをパターンリストに追加する
  579.  
  580. static void add_patlist(PAT *pat)
  581. // pat: 追加するパターンデータ。複製は作られず、そのまま追加される。
  582. {
  583.     if (patlist == NULL)
  584.         patlist = pat;
  585.     else {
  586.         PAT *p;
  587.         for (p = patlist;  p->next != NULL;  p = p->next)
  588.             ;
  589.         p->next = pat;
  590.     }
  591. }
  592.  
  593. // ● パターンデータをパターンリストから削除する
  594.  
  595. static void del_patlist(PAT *pat)
  596. // pat : 削除するパターンデータへのポインタ。
  597. //       パターンリスト内にこのポインタがあれば、その部分が削除される。
  598. {
  599.     PAT *prepp,*pp;
  600.     prepp = NULL;
  601.     for (pp=patlist; pp!=NULL; ) {
  602.         PAT *nextpp;
  603.         nextpp = pp->next;
  604.         if (pp == pat) {
  605.             if (prepp != NULL)
  606.                 prepp->next = pp->next;
  607.             else
  608.                 patlist     = pp->next;
  609.             destroyPAT(pp);
  610.         } else
  611.             prepp = pp;
  612.         pp = nextpp;
  613.     }
  614. }
  615.  
  616.  
  617. // パターンリスト全体を消去し、メモリを解放する
  618.  
  619.  
  620. static void clear_patlist()
  621. {
  622.     PAT *pp,*next;
  623.     for (pp=patlist; pp!=NULL; )
  624.     {
  625.         next = pp->next;
  626.         del_patlist(pp);
  627.         pp = next;
  628.     }
  629. }
  630.  
  631.  
  632. /*--------------------------------------------------------*/
  633. /*    パターンを画面上で範囲指定し、バッファに登録する    */
  634. /*--------------------------------------------------------*/
  635.  
  636.  
  637. // ● ユーザーにパターンを選択(範囲指定)させる
  638.  
  639.  
  640. static int selectPattern(PAT *pat)
  641. // 返値 : 0=選択が普通に終了した  1=選択がキャンセルされた
  642. //        -1=メモリ不足で選択できない
  643. {
  644.     int step;  int x1,y1,x2,y2;  int r;
  645.     int lat2xlen,lat2ylen; DMimage_getlatticesize(&lat2xlen,&lat2ylen);
  646.     r = 0;
  647.     void drawcsr(int msx, int msy)
  648.     {
  649.         int tx = DMimage_getx(msx), ty = DMimage_gety(msy);
  650.         if (step==1)
  651.         {
  652.             int p1=x1,p2=y1,p3=tx,p4=ty;
  653.             if (p1 > p3) swap(p1,p3);
  654.             if (p2 > p4) swap(p2,p4);
  655.             if (areaadj)
  656.             {
  657.                 p1-=p1%lat2xlen, p2-=p2%lat2ylen;
  658.                 p3=p3-p3%lat2xlen+lat2xlen-1, p4=p4-p4%lat2ylen+lat2ylen-1;
  659.             }
  660.             EIMboxline(p1,p2,p3,p4,white,DrawXOR);
  661.         }
  662.     }
  663.     step = 0;
  664.     int zr = DMimage_getzoomrate();
  665.     for (;;)
  666.     {
  667.         int prex,prey;
  668.         if (step == 0 || areaadj)
  669.             DMdispcsr(ms.x,ms.y);
  670.         drawcsr((prex=ms.x),(prey=ms.y));
  671.         for (;;)
  672.         {
  673.             ms_get(&ms);
  674.             if (ms.dx!=0 || ms.dy!=0 || ms.btn1!=OFF || ms.btn2!=OFF ||
  675.                 key_chk()!=0)
  676.                 break;
  677.         }
  678.         if (step == 0 || areaadj)
  679.             DMerasecsr();
  680.         drawcsr(prex,prey);        // 消去
  681.         if (step==0 || step==1)
  682.             scrollForCsr(1,1);
  683.         else
  684.             scrollForCsr((x2-x1+1)*zr,(y2-y1+1)*zr);
  685.         if (ms.btn1 == OFFON)
  686.         {
  687.             if (step==0)                // 範囲指定開始
  688.                 step=1,x1=DMimage_getx(ms.x),y1=DMimage_gety(ms.y);
  689.             else if (step==1)         // 範囲指定完了
  690.             {
  691.                 x2=DMimage_getx(ms.x),y2=DMimage_gety(ms.y);
  692.                 if (x1>x2)  swap(x1,x2);
  693.                 if (y1>y2)  swap(y1,y2);
  694.                 if (areaadj)
  695.                 {
  696.                     x1 = x1 - x1 % lat2xlen;
  697.                     y1 = y1 - y1 % lat2ylen;
  698.                     x2 = x2 - x2 % lat2xlen + lat2xlen - 1;
  699.                     y2 = y2 - y2 % lat2ylen + lat2ylen - 1;
  700.                 }
  701.                 int ixlen,iylen;
  702.                 menu_getbuttonxy(&patternmenu,itemPatBuf,NULL,NULL,&ixlen,&iylen);
  703.                 if (x2-x1+1 > ixlen/PATZOOM)
  704.                     x2 = x1 + ixlen/PATZOOM - 1;
  705.                 if (y2-y1+1 > iylen/PATZOOM)
  706.                     y2 = y1 + iylen/PATZOOM - 1;
  707.                 int dispx,dispy;
  708.                 DMimage_getdispxy(&dispx,&dispy);
  709.                 ms.x=(x1-dispx)*zr, ms.y=(y1-dispy)*zr;
  710.                 mous_setpos(&ms,ms.x,ms.y);
  711.                 scrollForCsr(1,1);
  712.                 pat->xlen = x2-x1+1;
  713.                 pat->ylen = y2-y1+1;
  714.                 {
  715.                     int gcd(int a, int b)
  716.                     {
  717.                         if (b == 0)    return a;
  718.                         else        return gcd(b, a%b);
  719.                     }
  720.                     int g = gcd(zr,zr);
  721.                     pat->zoomx = zr / g;
  722.                     pat->zoomy = zr / g;
  723.                 }
  724.                 {
  725.                     int xlen,ylen;
  726.                     xlen = x2-x1+1;
  727.                     ylen = y2-y1+1;
  728.                     if (mode == MODE32K)
  729.                         pat->patbufsize = 2 * xlen * ylen;
  730.                     else
  731.                         pat->patbufsize = 4 * ((xlen+7)/8) * ylen;
  732.                 }
  733.                 if ((pat->patbuf = malloc(pat->patbufsize)) != NULL)
  734.                 {
  735.                     page_edit();
  736.                     EIMgetblock(pat->patbuf, x1,y1,x2-x1+1,y2-y1+1);
  737.                     page_menu();
  738.                 }
  739.                 else
  740.                 {
  741.                     r = -1;
  742.                     break;
  743.                 }
  744.                 break;
  745.             }
  746.         }
  747.         else if (ms.btn2 == OFFON)
  748.         {
  749.             if (step == 1)
  750.                 step = 0;
  751.             else
  752.             {
  753.                 r = 1;
  754.                 break;
  755.             }
  756.         }
  757.     }
  758.     return r;
  759. }
  760.  
  761.  
  762. // ● ユーザーに、 パターンをパターンバッファへ登録させる
  763.  
  764.  
  765. static int do_storePattern(PAT *pat)
  766. // pat をメモリ中で複製して、それをリストに追加する
  767. {
  768.     PAT *newpat;
  769.     if ((newpat = dupPAT(pat)) != NULL)
  770.     {
  771.         newpat->selected = NO;
  772.         newpat->nodisp = NO;
  773.         newpat->next = NULL;
  774.         BUTTON *ip;
  775.         add_patlist(newpat);
  776.         return 0;
  777.     }
  778.     else
  779.         return -1;
  780. }
  781.  
  782.  
  783. /*--------------------------------------------------------*/
  784. /*    パターンを編集画面からパターンバッファへ登録する    */
  785. /*--------------------------------------------------------*/
  786.  
  787.  
  788. static int storePattern_sub(PAT *pat)
  789. {
  790.     int r = 0;
  791.     int step;  int x1,y1,x2,y2;
  792.     void drawcsr(int msx, int msy)
  793.     {
  794.         int tx,ty;
  795.         tx = sx2bx(msx);
  796.         ty = sy2by(msy);
  797.         page_edit();
  798.         grboxline(tx,ty,pat->xlen*pat->zoomx,pat->ylen*pat->zoomy,white,DrawXOR);
  799.         page_menu();
  800.     }
  801.     int zr = DMimage_getzoomrate();
  802.     for (;;)
  803.     {
  804.         int prex,prey;
  805.         DMdispcsr(ms.x,ms.y);
  806.         drawcsr((prex=ms.x),(prey=ms.y));
  807.         for (;;)
  808.         {
  809.             ms_get(&ms);
  810.             if (ms.dx!=0 || ms.dy!=0 || ms.btn1!=OFF || ms.btn2!=OFF ||
  811.              key_chk()!=0)
  812.                 break;
  813.         }
  814.         DMerasecsr();
  815.         drawcsr(prex,prey);        // 消去
  816.         // カーソル移動をパターンバッファ内に制限する
  817.         {
  818.             int ix,iy,ixlen,iylen;
  819.             menu_getbuttonxy(&patternmenu,itemPatBuf,&ix,&iy,&ixlen,&iylen);
  820.             ms.x = _min(_max(ix, ms.x),
  821.                         ix+ixlen - pat->xlen*pat->zoomx*zr);
  822.             ms.y = _min(_max(iy, ms.y),
  823.                         iy+iylen - pat->ylen*pat->zoomy*zr);
  824.             mous_setpos(&ms,ms.x,ms.y);
  825.             scrollForCsr(pat->xlen*pat->zoomx*zr,pat->ylen*pat->zoomy*zr);
  826.         }
  827.         if (ms.btn1 == OFFON)
  828.         {
  829.             // PAT 構造体の完全化と、 パターンリストへの追加
  830.             PAT newpat;
  831.             newpat = *pat;
  832.             newpat.name[0] = '\0';
  833.             newpat.subname[0] = '\0';
  834.             newpat.selected = NO;
  835.             newpat.nodisp = NO;
  836.             int ix,iy;
  837.             menu_getbuttonxy(&patternmenu,itemPatBuf,&ix,&iy,NULL,NULL);
  838.             newpat.bufx = sx2bx(ms.x - ix);
  839.             newpat.bufy = sy2by(ms.y - iy);
  840.             if (do_storePattern(&newpat) != 0)
  841.                 r = -1;
  842.             disp_patterns_all_new();
  843.             if (r != 0)
  844.                 break;
  845.         }
  846.         if (ms.btn2 == OFFON)
  847.             break;
  848.     }
  849.     return r;
  850. }
  851.  
  852.  
  853. static int storePattern()
  854. // 返値 0=成功  -1=メモリ不足
  855. {
  856.     PAT pat;
  857.     int r;
  858.     for (;;)
  859.     {
  860.         menu_erase(&patternmenu);
  861.         resetPage1();
  862.         DMimage_refresh();
  863.         r = selectPattern(&pat);
  864.         setPage1();
  865.         menu_disp(&patternmenu);
  866.         if (r == 0) {
  867.             int r2 = storePattern_sub(&pat);
  868.             free(pat.patbuf);
  869.             if (r2 < 0)
  870.                 return -1;
  871.         } else if (r == 1)
  872.             break;
  873.         else if (r < 0)
  874.             return -1;
  875.     }
  876.     return 0;
  877. }
  878.  
  879.  
  880. /*--------------------------------------------------------*/
  881. /*                   パターンを複製する                   */
  882. /*--------------------------------------------------------*/
  883.  
  884.  
  885. static int duplicatePattern(PAT *pp)
  886. {
  887.     PAT newpat;
  888.     newpat = *pp;
  889.     newpat.bufx += 4;
  890.     newpat.bufy += 4;
  891.     return do_storePattern(&newpat);
  892. }
  893.  
  894.  
  895. /*--------------------------------------------------------*/
  896. /*   パターンバッファをクリック・ドラックしたときの処理    */
  897. /*--------------------------------------------------------*/
  898.  
  899.  
  900. static void touchPat_1(PAT *pp)
  901. /*
  902.     パターンバッファ上のパターンを左クリック/左ドラッグしたときの処理
  903. */
  904. {
  905.     int zr = DMimage_getzoomrate();
  906.     while (ms.btn1 == OFFON || ms.btn1 == ON)
  907.     {
  908.         DMdispcsr(ms.x, ms.y);
  909.         do
  910.         {
  911.             ms_get(&ms);
  912.         } while (ms.dx==0 && ms.dy==0 && ms.btn1==ON);
  913.         DMerasecsr();
  914.         if (ms.dx != 0 || ms.dy != 0)    // ドラッグされたなら
  915.         {
  916.             pp->nodisp = YES;
  917.             disp_patterns_all_new();
  918.             int rx,ry;
  919.             rx = (ms.x-ms.dx) - bufx2sx(pp->bufx);
  920.             ry = (ms.y-ms.dy) - bufy2sy(pp->bufy);
  921.             ms.x-=rx,rx=0;
  922.             ms.y-=ry,ry=0;
  923.             mous_setpos(&ms,ms.x,ms.y);
  924.             void drawpatcsr(int msx,int msy)
  925.             {
  926.                 int x1,y1;
  927.                 x1 = bufx2sx(sx2bufx(msx - rx));
  928.                 y1 = bufy2sy(sy2bufy(msy - ry));
  929.                 grboxline(x1,y1,pp->xlen*pp->zoomx*zr,
  930.                           pp->ylen*pp->zoomy*zr,White,DrawXOR);
  931.             }
  932.             while (ms.btn1 == ON)
  933.             {
  934.                 int prex,prey;
  935.                 DMdispcsr(ms.x, ms.y);
  936.                 drawpatcsr((prex=ms.x),(prey=ms.y));
  937.                 do
  938.                 {
  939.                     ms_get(&ms);
  940.                 } while (ms.dx==0 && ms.dy==0 && ms.btn1==ON);
  941.                 DMerasecsr();
  942.                 drawpatcsr(prex,prey);
  943.                 // limitCsrPos();
  944.                 // カーソル移動をパターンバッファ内に制限する
  945.                 {
  946.                     int ix,iy,ixlen,iylen;
  947.                     menu_getbuttonxy(&patternmenu,itemPatBuf,&ix,&iy,&ixlen,&iylen);
  948.                     ms.x = _min(_max(ix, ms.x),
  949.                                 ix+ixlen - pp->xlen*pp->zoomx*zr);
  950.                     ms.y = _min(_max(iy, ms.y),
  951.                                 iy+iylen - pp->ylen*pp->zoomy*zr);
  952.                     mous_setpos(&ms,ms.x,ms.y);
  953.                     scrollForCsr(pp->xlen*pp->zoomx*zr,
  954.                                  pp->ylen*pp->zoomy*zr);
  955.                 }
  956.             }
  957.             pp->bufx = sx2bufx(ms.x-rx);
  958.             pp->bufy = sy2bufy(ms.y-ry);
  959.             pp->nodisp = NO;
  960.         }
  961.         else                        // クリックされたなら
  962.         {
  963.             if (!pp->selected) {
  964.                 pp->selected = YES;
  965.                 //if (selnum < SELNUM) {
  966.                 //    selpat[selnum] = pp;
  967.                 //    pp->selected = YES;
  968.                 //    selnum++;
  969.                 //}
  970.             } else {
  971.                 pp->selected = NO;
  972.                 //int i;
  973.                 //for (i=0; i < SELNUM; i++) {
  974.                 //    if (selpat[i] == pp) {
  975.                 //        if (i < SELNUM-1)
  976.                 //            memcpy(&selpat[i],&selpat[i+1],sizeof(PAT*) * (SELNUM-i-1));
  977.                 //        selnum--;
  978.                 //        selpat[selnum] = NULL;
  979.                 //    }
  980.                 //}
  981.             }
  982.         }
  983.     }
  984.     disp_patterns_all_new();
  985. }
  986.  
  987.  
  988. static int touchPat_2(PAT *pp)
  989. /*
  990.     パターンバッファ上のパターンが右クリックされたときの処理
  991.     返値: 0=成功 -1=メモリ不足
  992. */
  993. {
  994.     int err = 0;
  995.     curpat = pp;
  996.     if (menu_dispxy(ms.x, ms.y, &patsubmenu) != 0)
  997.         return -1;
  998.     for (;;) {
  999.         DMdispcsr(ms.x,ms.y);
  1000.         ms_get(&ms);
  1001.         DMerasecsr();
  1002.         limitCsrPos();
  1003.         if (ms.btn1 == OFFON) {
  1004.             int a; int ax,ay;
  1005.             a = menu_where(ms.x,ms.y,&patsubmenu, &ax,&ay,NULL);
  1006.             if (a == SitemPatName) {
  1007.                 int r;
  1008.                 int ix,iy,ixlen,iylen;
  1009.                 menu_getbuttonxy(&patsubmenu,SitemPatName,
  1010.                                  &ix,&iy,&ixlen,&iylen);
  1011.                 r = editStr(ix+1,iy+1,ixlen/8,curpat->name,41,-1);
  1012.             } else if (a == SitemPatSubName) {
  1013.                 int r;
  1014.                 int ix,iy,ixlen,iylen;
  1015.                 menu_getbuttonxy(&patsubmenu,SitemPatSubName,
  1016.                                  &ix,&iy,&ixlen,&iylen);
  1017.                 r = editStr(ix+1,iy+1,ixlen/8,curpat->subname,15,-1);
  1018.             } else if (a == SitemDup) {
  1019.                 err = duplicatePattern(curpat);
  1020.                 break;
  1021.             } else if (a == SitemDelete) {
  1022.                 del_patlist(curpat);
  1023.                 break;
  1024.             } else if (a == SitemPut)
  1025.             {
  1026.                 MON;
  1027.                 menu_erase();
  1028.                 menu_erase();
  1029.                 resetPage1();
  1030.                 for (;;)
  1031.                 {
  1032.                     void drawcsr(int msx,int msy)
  1033.                     {
  1034.                         MOFF;
  1035.                         int tx=DMimage_getx(msx),ty=DMimage_gety(msy);
  1036.                         EIMrboxline(tx,ty,curpat->xlen,curpat->ylen,
  1037.                                     white,DrawXOR);
  1038.                         MON;
  1039.                     }
  1040.                     int prex,prey;
  1041.                     if (areaadj)
  1042.                         DMdispcsr(ms.x,ms.y);
  1043.                     drawcsr((prex=ms.x),(prey=ms.y));
  1044.                     do
  1045.                     {
  1046.                         ms_get(&ms);
  1047.                     } while (ms.dx==0 && ms.dy==0 &&
  1048.                              ms.btn1==OFF && ms.btn2==OFF && key_chk()==0);
  1049.                     if (areaadj)
  1050.                         DMerasecsr();
  1051.                     drawcsr(prex,prey);
  1052.                     int zr = DMimage_getzoomrate();
  1053.                     scrollForCsr(curpat->xlen*zr, curpat->ylen*zr);
  1054.                     if (ms.btn1 == OFFON)
  1055.                     {
  1056.                         int dx=DMimage_getx(ms.x),dy=DMimage_gety(ms.y);
  1057.                         matte_putblock(dx,dy,curpat->xlen,curpat->ylen,
  1058.                                        curpat->patbuf, blkop);
  1059.                     }
  1060.                     if (ms.btn2 == OFFON)
  1061.                     {
  1062.                         break;
  1063.                     }
  1064.                 }
  1065.                 MOFF;
  1066.                 setPage1();
  1067.                 menu_disp(&patternmenu);
  1068.                 goto end;
  1069.             }
  1070.         } else if (ms.btn2 == OFFON)
  1071.             break;
  1072.     }
  1073.     menu_erase();
  1074.     disp_patterns_all_new();
  1075. end:
  1076.     return err;
  1077. }
  1078.  
  1079.  
  1080. static int touchPatBuf(int btn)
  1081. // btn : 1=左ボタン 2=右ボタン
  1082. {
  1083.     PAT *pp;
  1084.     pp = jdgPattern(ms.x, ms.y);
  1085.     if (pp == NULL || pp->nodisp)
  1086.         return 0;
  1087.     if (btn == 1)
  1088.         touchPat_1(pp);
  1089.     else
  1090.         return touchPat_2(pp);
  1091.     return 0;
  1092. }
  1093.  
  1094.  
  1095. /*--------------------------------------------------------*/
  1096. /*                  パターンの保存・読込                   */
  1097. /*--------------------------------------------------------*/
  1098.  
  1099.  
  1100. static    bool    sw_savesel;        // SWitch to SAVE SELected-patterns
  1101. static    bool    sw_loadadd;        // SWitch to LOAD patterns ADDitionally
  1102.  
  1103.  
  1104. // typedef struct _pat {
  1105. //     struct _pat    *next;            // リスト化のためのポインタ
  1106. //     int            xlen, ylen;        // パターンの大きさ
  1107. //     int            bufx, bufy;        // パターンバッファ内での位置
  1108. //     int            patbufsize;        // パターンデータのバイト数
  1109. //     char        *patbuf;        // パターンデータへのポインタ
  1110. //     bool        selected;        // 選択されているなら YES
  1111. //     bool        disp;            // パターンバッファ表示時に表示するかどうか
  1112. // } PAT;
  1113.  
  1114.  
  1115. static void do_savePattern(char **filelist)
  1116. {
  1117.     char pathbuf[_MAX_PATH];
  1118.     FILE *fp;
  1119.     add_fname_ext(pathbuf, filelist[0], "PAT");
  1120.     if ((fp = fopen(filelist[0], "wb")) == NULL)
  1121.         return;
  1122.     PAT *pp;
  1123.     for (pp=patlist; pp!=NULL; pp=pp->next)
  1124.     {
  1125.         if (sw_savesel)
  1126.         {
  1127.             if (pp->selected)
  1128.             {
  1129.                 PAT pathead;
  1130.                 pathead = *pp;
  1131.                 pathead.selected = NO;    // 選択スイッチは OFF にしてセーブ
  1132.                 fwrite(&pathead, sizeof(PAT), 1, fp);
  1133.                 fwrite(pp->patbuf, 1, pp->patbufsize, fp);
  1134.             }
  1135.         }
  1136.         else
  1137.         {
  1138.             fwrite(pp, sizeof(PAT), 1, fp);
  1139.             fwrite(pp->patbuf, 1, pp->patbufsize, fp);
  1140.         }
  1141.     }
  1142.     fclose(fp);
  1143. }
  1144.  
  1145.  
  1146. static void do_loadPattern(char **filelist)
  1147. {
  1148.     FILE *fp;
  1149.     PAT pat, *pp, *prepp;
  1150.     if ((fp = fopen(filelist[0], "rb")) == NULL)
  1151.         return;
  1152.     if (!sw_loadadd)
  1153.     {
  1154.         // 新規読み込みの場合
  1155.         clear_patlist();
  1156.         prepp = NULL;
  1157.     }
  1158.     else
  1159.     {
  1160.         // 追加読み込みの場合
  1161.         if (patlist == NULL)
  1162.             prepp = NULL;
  1163.         else
  1164.         {
  1165.             for (pp = patlist;  pp->next != NULL;  pp = pp->next)
  1166.                 ;
  1167.             prepp = pp;
  1168.         }
  1169.     }
  1170.     fread(&pat, sizeof(PAT), 1, fp);
  1171.     for ( ;  !feof(fp);  prepp = pp) {
  1172.         if ((pp = malloc(sizeof(PAT))) == NULL)
  1173.             break;
  1174.         (prepp==NULL ? patlist = pp : prepp->next = pp);
  1175.         *pp = pat;
  1176.         if ((pp->patbuf = malloc(pp->patbufsize)) == NULL)
  1177.             break;
  1178.         fread(pp->patbuf, 1, pp->patbufsize, fp);
  1179.         fread(&pat, sizeof(PAT), 1, fp);
  1180.     }
  1181.     if (prepp != NULL)
  1182.         prepp->next = NULL;
  1183.     fclose(fp);
  1184. }
  1185.  
  1186.  
  1187. static void save_all_patterns()
  1188. {
  1189.     sw_savesel = NO;
  1190.     file_menu("すべてのパターンを保存する [.PAT]", do_savePattern);
  1191. }
  1192.  
  1193.  
  1194. static void save_sel_patterns()
  1195. {
  1196.     sw_savesel = YES;
  1197.     file_menu("選択中のパターンを保存する [.PAT]", do_savePattern);
  1198. }
  1199.  
  1200.  
  1201. static void load_patterns_new()
  1202. {
  1203.     sw_loadadd = NO;
  1204.     file_menu("パターンを新規に読み込む", do_loadPattern);
  1205. }
  1206.  
  1207.  
  1208. static void load_patterns_add()
  1209. {
  1210.     sw_loadadd = YES;
  1211.     file_menu("パターンを追加読み込みする", do_loadPattern);
  1212. }
  1213.  
  1214.  
  1215. /*--------------------------------------------------------*/
  1216. /*                 スプライトデータの作成                 */
  1217. /*--------------------------------------------------------*/
  1218.  
  1219.  
  1220. static void output_sprite_data_C(char *fname)
  1221. {
  1222.     FILE *fp;
  1223.     PAT *pp;
  1224.     if ((fp = fopen(fname,"w")) == NULL)
  1225.         return;
  1226.     fprintf(fp,"static char sprite_32k[][512] = {\n");
  1227.     for (pp = patlist;  pp != NULL;  pp = pp->next)
  1228.     {
  1229.         char *name = NULL;
  1230.         int px,py;
  1231.         if (!pp->selected || pp->nodisp)
  1232.             continue;
  1233.         // 出力するパターン名へのポインタを name に設定する
  1234.         if (pp->name[0] != 0)
  1235.             name = pp->name;
  1236.         else if (pp->subname[0] != 0)
  1237.             name = pp->subname;
  1238.         if (name != NULL)
  1239.             fprintf(fp, "\n\t/* %s */\n", name);
  1240.         // パターンデータを出力する
  1241.         for (py = 0;  py < (pp->ylen+15)/16;  py++)
  1242.         {
  1243.             for (px = 0;  px < (pp->xlen+15)/16;  px++)
  1244.             {
  1245.                 int line,clm;
  1246.                 for (line = 0;  line < 32;  line++) {
  1247.                     fprintf(fp, (line==0 ? "\t{ " : "\t  "));
  1248.                     for (clm = 0;  clm < 8;  clm++) {
  1249.                         int ix,iy,dat;
  1250.                         ix = px*16 + (line%2)*8 + clm;
  1251.                         iy = py*16 + line/2;
  1252.                         if (ix >= pp->xlen || iy >= pp->ylen)
  1253.                             dat = 0;
  1254.                         else
  1255.                             dat = get_pat_pixel(pp, ix, iy);
  1256.                         if (dat == 0)
  1257.                             dat |= 0x8000;    // マスクビットをセット
  1258.                         fprintf(fp, "%3d,%3d", dat&0xff, dat>>8);
  1259.                         fprintf(fp, (clm < 8-1 ? "," : ""));
  1260.                     }
  1261.                     fprintf(fp, (line < 32-1 ? ",\n" : " }"));
  1262.                 }
  1263.                 fprintf(fp, (pp->next != NULL ? ",\n" : "\n"));
  1264.             }
  1265.         }
  1266.     }
  1267.     fprintf(fp,"};\n");
  1268.     fclose(fp);
  1269. }
  1270.  
  1271.  
  1272. static void output_sprite_data_BASIC(char *fname)
  1273. {
  1274.     FILE *fp;
  1275.     PAT *pp;
  1276.     if ((fp = fopen(fname,"w")) == NULL)
  1277.         return;
  1278.     int lnum=10000;
  1279.     fprintf(fp,"%d ' 32768色 スプライトパターンデータ\n", lnum);
  1280.     lnum += 10;
  1281.     for (pp = patlist;  pp != NULL;  pp = pp->next)
  1282.     {
  1283.         char *name = NULL;
  1284.         int px,py;
  1285.         if (!pp->selected || pp->nodisp)
  1286.             continue;
  1287.         // 出力するパターン名へのポインタを name に設定する
  1288.         if (pp->name[0] != 0)
  1289.             name = pp->name;
  1290.         else if (pp->subname[0] != 0)
  1291.             name = pp->subname;
  1292.         fprintf(fp, "%d '  %s\n", lnum, (name!=NULL?name:""));
  1293.         lnum += 10;
  1294.         // パターンデータを出力する
  1295.         int xpatn,ypatn;
  1296.         xpatn = (pp->xlen+15)/16;
  1297.         ypatn = (pp->ylen+15)/16;
  1298.         for (py = 0;  py < ypatn;  py++)
  1299.         {
  1300.             for (px = 0;  px < xpatn;  px++)
  1301.             {
  1302.                 int line,clm;
  1303.                 for (line = 0;  line < 32;  line++) {
  1304.                     if (xpatn > 1 || ypatn > 1)
  1305.                     {
  1306.                         fprintf(fp,"%d '    (%d,%d)\n", lnum, px,py);
  1307.                         lnum += 10;
  1308.                     }
  1309.                     fprintf(fp,"%d DATA ",lnum);
  1310.                     lnum += 10;
  1311.                     for (clm = 0;  clm < 8;  clm++) {
  1312.                         int ix,iy,dat;
  1313.                         ix = px*16 + (line%2)*8 + clm;
  1314.                         iy = py*16 + line/2;
  1315.                         if (ix >= pp->xlen || iy >= pp->ylen)
  1316.                             dat = 0;
  1317.                         else
  1318.                             dat = get_pat_pixel(pp, ix, iy);
  1319.                         if (dat == 0)
  1320.                             dat |= 0x8000;    // マスクビットをセット
  1321.                         fprintf(fp, "%04x", dat);
  1322.                         if (clm < 8-1)
  1323.                             fprintf(fp, ",");
  1324.                     }
  1325.                     fprintf(fp,"\n");
  1326.                 }
  1327.             }
  1328.         }
  1329.     }
  1330.     fclose(fp);
  1331. }
  1332.  
  1333.  
  1334. static void output_sprite_data_binary(char *fname, int info)
  1335. /*
  1336.     info :
  1337.         スプライト情報ファイル(番号とスプライト名の対応)を出力するか
  1338.         0 = 出力しない  1 = 出力する
  1339. */
  1340. {
  1341.     FILE *fp, *fp_info;  PAT *pp;  int patn;
  1342.     if ((fp = fopen(fname,"wb")) == NULL)
  1343.         return;
  1344.     if (info)
  1345.     {
  1346.         if ((fp_info = fopen(trans_fname_ext(fname,"SPI"), "w")) == NULL)
  1347.             { fclose(fp);  return; }
  1348.     }
  1349.     for (pp = patlist, patn=0;  pp != NULL;  pp = pp->next, patn++)
  1350.     {
  1351.         int px,py;
  1352.         if (!pp->selected || pp->nodisp)
  1353.             continue;
  1354.         if (info)
  1355.         {
  1356.             char *name = NULL;
  1357.             // 出力するパターン名へのポインタを name に設定する
  1358.             if (pp->name[0] != 0)
  1359.                 name = pp->name;
  1360.             else if (pp->subname[0] != 0)
  1361.                 name = pp->subname;
  1362.             fprintf(fp_info, "%3d: %s\n", patn, (name==NULL ? "###" : name));
  1363.         }
  1364.         // パターンデータを出力する
  1365.         for (py = 0;  py < (pp->ylen+15)/16;  py++)
  1366.         {
  1367.             for (px = 0;  px < (pp->xlen+15)/16;  px++)
  1368.             {
  1369.                 int xx,yy;
  1370.                 for (yy=0; yy<16; yy++)
  1371.                 {
  1372.                     int tdat;
  1373.                     for (xx=0; xx<16; xx++)
  1374.                     {
  1375.                         int ix,iy,dat;
  1376.                         ix = px*16 + xx;
  1377.                         iy = py*16 + yy;
  1378.                         if (ix >= pp->xlen || iy >= pp->ylen)
  1379.                             dat = 0;
  1380.                         else
  1381.                             dat = get_pat_pixel(pp, ix, iy);
  1382.                         if (mode == MODE32K)
  1383.                         {
  1384.                             if (dat == 0)
  1385.                                 dat |= 0x8000;    // マスクビットをセット
  1386.                             putc(dat & 0xff, fp);
  1387.                             putc((dat >> 8) & 0xff, fp);
  1388.                         }
  1389.                         else
  1390.                         {
  1391.                             if (xx%2 == 0)
  1392.                                 tdat = dat & 0xf;
  1393.                             else
  1394.                                 putc((tdat<<4)|(dat&0xf), fp);
  1395.                         }
  1396.                     }
  1397.                 }
  1398.             }
  1399.         }
  1400.     }
  1401.     if (info)
  1402.         fclose(fp_info);
  1403.     fclose(fp);
  1404. }
  1405.  
  1406.  
  1407. static    void    do_makesprite(char **filelist, int format)
  1408. {
  1409.     char pathbuf[_MAX_PATH];
  1410.     switch (format)
  1411.     {
  1412.     case 0:
  1413.         add_fname_ext(pathbuf, filelist[0], "C");
  1414.         output_sprite_data_C(pathbuf);
  1415.         break;
  1416.     case 1:
  1417.         add_fname_ext(pathbuf, filelist[0], "BAS");
  1418.         output_sprite_data_BASIC(pathbuf);
  1419.         break;
  1420.     case 2:
  1421.         add_fname_ext(pathbuf, filelist[0], "SPB");
  1422.         output_sprite_data_binary(pathbuf, 0);
  1423.         break;
  1424.     case 3:
  1425.         add_fname_ext(pathbuf, filelist[0], "SPB");
  1426.         output_sprite_data_binary(pathbuf, 1);
  1427.         break;
  1428.     }
  1429. }
  1430.  
  1431.  
  1432. static    void    conv_to_sprite()
  1433. {
  1434.     char *xi[] = {
  1435.         "ファイル形式",
  1436.         "[.C  ] C言語の配列",
  1437.         "[.BAS] BASICのDATA",
  1438.         "[.SPB] ベタ(情報なし)",
  1439.         "[.SPB] ベタ(情報あり)",
  1440.         NULL
  1441.     };
  1442.     file_menu_exp("選択中のパターンをスプライトデータに変換する",
  1443.                   do_makesprite, xi);
  1444. }
  1445.  
  1446.  
  1447. /*--------------------------------------------------------*/
  1448. /*                パターンを文字列になおす                */
  1449. /*--------------------------------------------------------*/
  1450.  
  1451.  
  1452. static void do_characterize(char **filelist)
  1453. {
  1454.     char pathbuf[_MAX_PATH];
  1455.     FILE *fp;
  1456.     PAT *pp;
  1457.     add_fname_ext(pathbuf, filelist[0], "PTS");
  1458.     if ((fp = fopen(pathbuf,"w")) == NULL)
  1459.         return;
  1460.     for (pp=patlist; pp!=NULL; pp=pp->next)
  1461.     {
  1462.         if (!pp->selected || pp->nodisp)
  1463.             continue;
  1464.         char *name = NULL;
  1465.         if (pp->name[0] != 0)
  1466.             name = pp->name;
  1467.         else if (pp->subname[0] != 0)
  1468.             name = pp->subname;
  1469.         if (name != NULL)
  1470.             fprintf(fp, "%s\n", pp->name);
  1471.         int ix,iy;
  1472.         for (iy=0; iy < pp->ylen; iy++)
  1473.         {
  1474.             for (ix=0; ix < pp->xlen; ix++)
  1475.             {
  1476.                 if (mode == MODE32K)
  1477.                 {
  1478.                     fprintf(fp, "%04x", get_pat_pixel(pp,ix,iy));
  1479.                     if (ix+1 < pp->xlen)
  1480.                         fprintf(fp, " ");
  1481.                 }
  1482.                 else
  1483.                     fprintf(fp, "%01x", get_pat_pixel(pp,ix,iy));
  1484.             }
  1485.             fprintf(fp, "\n");
  1486.         }
  1487.         fprintf(fp, "\n");
  1488.     }
  1489.     fclose(fp);
  1490. }
  1491.  
  1492.  
  1493. static void conv_to_string()
  1494. {
  1495.     file_menu("選択中のパターンを文字列データ [.PTS] に変換",
  1496.               do_characterize);
  1497. }
  1498.  
  1499.  
  1500. /*--------------------------------------------------------*/
  1501. /*                  順表示アニメーション                  */
  1502. /*--------------------------------------------------------*/
  1503.  
  1504.  
  1505. static void animation()
  1506. {
  1507.     if (patlist == NULL)
  1508.         return;
  1509.     erase_patterns_all();
  1510.     PAT *pp;
  1511.     for (;;) {
  1512.         for (pp=patlist; pp!=NULL; pp=pp->next) {
  1513.             ms_get(&ms);
  1514.             limitCsrPos();
  1515.             if (ms.btn1 == OFFON || ms.btn2 == OFFON)
  1516.                 goto _end;
  1517.             if (pp->selected) {
  1518.                 pp->selected = NO;
  1519.                 if (ryosuke_pat)    // 作者オプション2がオンなら消す
  1520.                     erase_patterns_all();
  1521.                 dispOnePattern(pp, NO, YES);
  1522.                 int i;
  1523.                 for (i=0; i<5; i++) {
  1524.                     wait_vsync();
  1525.                 }
  1526.                 pp->selected = YES;
  1527.             }
  1528.         }
  1529.     }
  1530. _end:
  1531.     disp_patterns_all_new();
  1532. }
  1533.  
  1534.  
  1535. /*--------------------------------------------------------*/
  1536. /*                選択/表示スイッチの操作                */
  1537. /*--------------------------------------------------------*/
  1538.  
  1539.  
  1540. static void switch_select_and_disp(int itemnum)
  1541. // itemnum : クリックされたメニューアイテムの番号
  1542. {
  1543.     PAT *pp;
  1544.     switch (itemnum)
  1545.     {
  1546.     case itemSelectAll:
  1547.         for (pp = patlist;  pp != NULL;  pp = pp->next)
  1548.             if (!pp->nodisp)    pp->selected = YES;
  1549.         break;
  1550.     case itemSelectNothing:
  1551.         for (pp = patlist;  pp != NULL;  pp = pp->next)
  1552.             if (!pp->nodisp)    pp->selected = NO;
  1553.         break;
  1554.     case itemSelectReverse:
  1555.         for (pp = patlist;  pp != NULL;  pp = pp->next)
  1556.             if (!pp->nodisp)    pp->selected = !pp->selected;
  1557.         break;
  1558.     case itemDispAll:
  1559.         for (pp = patlist;  pp != NULL;  pp = pp->next)
  1560.             pp->nodisp = NO;
  1561.         break;
  1562.     case itemDispNothing:
  1563.         for (pp = patlist;  pp != NULL;  pp = pp->next)
  1564.             pp->nodisp = YES, pp->selected = NO;
  1565.         break;
  1566.     case itemDispReverce:
  1567.         for (pp = patlist;  pp != NULL;  pp = pp->next)
  1568.         {
  1569.             if (pp->nodisp)
  1570.                 pp->nodisp = NO;
  1571.             else
  1572.                 pp->nodisp = YES, pp->selected = NO;
  1573.         }
  1574.     }
  1575.     disp_patterns_all_new();
  1576. }
  1577.  
  1578.  
  1579. /*--------------------------------------------------------*/
  1580. /*             「パターン編集」コマンド 主処理              */
  1581. /*--------------------------------------------------------*/
  1582.  
  1583.  
  1584. void commandPattern()
  1585. {
  1586.     MOFF;
  1587.     // EIMbackup();   // 編集画面を保存
  1588.     // if (selnum == -1) {
  1589.     //     memset(selpat, 0, sizeof(PAT*) * SELNUM);
  1590.     //     selnum = 0;
  1591.     // }
  1592.     setPage1();
  1593.     menu_disp(&patternmenu);
  1594.     for (;;)
  1595.     {
  1596.         DMdispcsr(ms.x, ms.y);
  1597.         do
  1598.         {
  1599.             ms_get(&ms);
  1600.         } while (ms.dx==0 && ms.dy==0 && ms.btn1==OFF && ms.btn2==OFF && key_chk()==0);
  1601.         DMerasecsr();
  1602.         // scrollForCsr(1,1);
  1603.         limitCsrPos();
  1604.         if (ms.btn1 == OFFON)
  1605.         {
  1606.             int a;  int ax,ay;  SCROLLBAR *sbarp;
  1607.             a = menu_where(ms.x,ms.y,&patternmenu, &ax,&ay,&sbarp);
  1608.             switch (a)
  1609.             {
  1610.             int r;
  1611.             PAT *pp;
  1612.             case itemScrollBar:
  1613.                 menu_touchscrollbar(sbarp, ax,ay);
  1614.                 break;
  1615.             case itemExit:
  1616.                 goto _end;
  1617.             case itemPatBuf:
  1618.                 touchPatBuf(1);
  1619.                 break;
  1620.             case itemStorePattern:
  1621.                 if (storePattern() != 0)
  1622.                     goto nomem;
  1623.                 break;
  1624.             case itemDeleteSelPat:
  1625.                 if (check_yes_no("選択中のパターンを抹消します。\nよろしいですか?")
  1626.                     == 0)
  1627.                 {
  1628.                     for (pp=patlist; pp!=NULL; )
  1629.                     {
  1630.                         PAT *next = pp->next;
  1631.                         if (pp->selected)
  1632.                             del_patlist(pp);
  1633.                         pp = next;
  1634.                     }
  1635.                     disp_patterns_all_new();
  1636.                 }
  1637.                 break;
  1638.             case itemDupSelPat:
  1639.                 for (pp=patlist; pp!=NULL; pp=pp->next)
  1640.                     if (pp->selected)
  1641.                         duplicatePattern(pp);
  1642.                 disp_patterns_all_new();
  1643.                 break;
  1644.             case itemDispOffSelPat:
  1645.                 for (pp=patlist; pp!=NULL; pp=pp->next)
  1646.                     if (pp->selected)
  1647.                         pp->selected = NO, pp->nodisp = YES;
  1648.                 disp_patterns_all_new();
  1649.                 break;
  1650.             case itemSaveAllPattern:
  1651.                 save_all_patterns();
  1652.                 break;
  1653.             case itemNewLoadPattern:
  1654.                 load_patterns_new();
  1655.                 disp_patterns_all_new();
  1656.                 break;
  1657.             case itemSaveSelPattern:
  1658.                 save_sel_patterns();
  1659.                 break;
  1660.             case itemAddLoadPattern:
  1661.                 load_patterns_add();
  1662.                 disp_patterns_all_new();
  1663.                 break;
  1664.             case itemConvToSprite:
  1665.                 conv_to_sprite();
  1666.                 break;
  1667.             case itemSelectAll:
  1668.             case itemSelectNothing:
  1669.             case itemSelectReverse:
  1670.             case itemDispAll:
  1671.             case itemDispNothing:
  1672.             case itemDispReverce:
  1673.                 switch_select_and_disp(a);
  1674.                 break;
  1675.             case itemSort:
  1676.                 sort_patlist();
  1677.                 disp_patterns_all_new();
  1678.                 break;
  1679.             case itemAnimation:
  1680.                 animation();
  1681.                 break;
  1682.             case itemConvToString:
  1683.                 conv_to_string();
  1684.             }
  1685.         }
  1686.         else if (ms.btn2 == OFFON)
  1687.         {
  1688.             int a;  int ax,ay;
  1689.             a = menu_where(ms.x,ms.y,&patternmenu, &ax,&ay,NULL);
  1690.             if (a == itemPatBuf)
  1691.             {
  1692.                 if (touchPatBuf(2) != 0)
  1693.                     goto nomem;
  1694.             } else
  1695.                 break;
  1696.         }
  1697.     }
  1698. _end:
  1699.     menu_erase(&patternmenu);
  1700.     resetPage1();
  1701.     DMimage_refresh();    // 編集画面を復帰
  1702.     MON;
  1703.     return;
  1704. nomem:
  1705.     menu_erase(&patternmenu);
  1706.     resetPage1();
  1707.     DMimage_refresh();    // 編集画面を復帰
  1708.     dispAttentionMsg("記憶容量不足のため、パターンの編集に支障があります");
  1709.     MON;
  1710. }
  1711.  
  1712.  
  1713.  
  1714. /* end of pattern.c */
  1715.  
  1716.